package com.caiden_micheal.position.service.impl;

import com.caiden_micheal.base.constant.LoggerHead;
import com.caiden_micheal.base.domain.AjxResult;
import com.caiden_micheal.base.dto.PageDTO;
import com.caiden_micheal.menu.utils.MenuUtil;
import com.caiden_micheal.base.utils.RedisUtil;
import com.caiden_micheal.base.vo.PageVo;
import com.caiden_micheal.menu.service.MenuService;
import com.caiden_micheal.org.domain.Org;
import com.caiden_micheal.org.mapper.OrgMapper;
import com.caiden_micheal.permission.domain.Permission;
import com.caiden_micheal.permission.mapper.PermissionMapper;
import com.caiden_micheal.position.vo.*;
import com.caiden_micheal.position.domain.Position;
import com.caiden_micheal.position.mapper.PositionMapper;
import com.caiden_micheal.position.service.PositionService;
import com.caiden_micheal.user.domain.PositionOrgUser;
import com.caiden_micheal.user.domain.User;
import com.caiden_micheal.user.domain.UserAuthority;
import com.caiden_micheal.user.mapper.PositionAuthorityMapper;
import com.caiden_micheal.user.mapper.PositionOrgUserMapper;
import com.caiden_micheal.user.mapper.UserMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;

@Service
public class PositionServiceImpl implements PositionService {
    private static final Logger logger = LoggerFactory.getLogger(PositionServiceImpl.class);
    @Autowired
    private PositionMapper positionMapper;
    @Autowired
    private PositionAuthorityMapper positionAuthorityMapper;
    @Autowired
    private PositionOrgUserMapper positionOrgUserMapper;
    @Autowired
    private OrgMapper orgMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Lazy
    @Autowired
    private MenuService menuService;

    @Override
    public List<UserAuthority> findPositionAuthorityListByUserId(Long id) {
        List<PositionOrgUser> positionList = positionOrgUserMapper.findPositionOrgUserByUserId(id);
        if (positionList.size() == 0) {
            return new ArrayList<>();
        }
        List<Long> ids = new ArrayList<>();
        for (PositionOrgUser positionOrgUser : positionList) {
            ids.add(positionOrgUser.getPositionId());
        }
        return positionAuthorityMapper.findBatchAuthorityIdByPositionIds(ids);
    }

    @Override
    public PageDTO findPositionsByCondition(PositionQueryVO positionQueryVO) {
        PageVo page = positionQueryVO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "positionQueryVO.page is Null!");
            return null;
        }
        List<Long> positionIdList = null;
        if (positionQueryVO.getAuthorityId() != null) {
            Permission permission = permissionMapper.findById(positionQueryVO.getAuthorityId());
            if (permission == null) {
                logger.warn(LoggerHead.warnHead() + "Permission Not Exist! authorityId: " + positionQueryVO.getAuthorityId());
                return null;
            }
            positionIdList = positionAuthorityMapper.findPositionIdsByAuthorityId(positionQueryVO.getAuthorityId());
            if (positionIdList.size() == 0) {
                return null;
            }
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<Position> positionList = positionMapper.findPositionListPaginationQuery(positionQueryVO, positionIdList);
        page.setCount(positionMapper.findPositionListQueryCount(positionQueryVO, positionIdList));
        return new PageDTO(positionList, page);
    }

    @Override
    public PageDTO positionQueryExcludeAuthority(PositionQueryVO positionQueryVO) {
        PageVo page = positionQueryVO.getPage();
        if (page == null) {
            logger.warn(LoggerHead.warnHead() + "positionQueryVO.page is Null!");
            return null;
        }
        List<Long> positionIdList = null;
        if (positionQueryVO.getAuthorityId() != null) {
            Permission permission = permissionMapper.findById(positionQueryVO.getAuthorityId());
            if (permission == null) {
                logger.warn(LoggerHead.warnHead() + "Permission Not Exist! authorityId: " + positionQueryVO.getAuthorityId());
                return null;
            }
            positionIdList = positionAuthorityMapper.findPositionIdsByAuthorityId(positionQueryVO.getAuthorityId());
            if (positionIdList.size() == 0) {
                positionIdList = null;
            }
        }
        page.setCurrentIndex((long) (page.getCurrentPage() - 1) * page.getPageSize());
        List<Position> positionList = positionMapper.findPositionListPaginationQueryExcludeAuthority(positionQueryVO, positionIdList);
        page.setCount(positionMapper.findPositionListQueryCountExcludeAuthority(positionQueryVO, positionIdList));
        return new PageDTO(positionList, page);
    }

    @Transactional
    @Override
    public AjxResult positionRemoveAuthority(PositionAuthorityRemoveVO positionAuthorityRemoveVO) {
        if (positionAuthorityRemoveVO == null || positionAuthorityRemoveVO.getAuthorityId() == null || positionAuthorityRemoveVO.getPositionId() == null) {
            return AjxResult.paramError("参数传入有误");
        }
        Permission permission = permissionMapper.findById(positionAuthorityRemoveVO.getAuthorityId());
        if (permission == null) {
            return AjxResult.paramError("权限不存在");
        }
        Position position = positionMapper.findById(positionAuthorityRemoveVO.getPositionId());
        if (position == null) {
            return AjxResult.paramError("职位不存在");
        }
        try {
            List<Permission> permissionList = MenuUtil.permissionRemoveListMerging(permission, menuService);
            List<Long> permissionIncludeIdList = positionAuthorityMapper.findAuthorityIdsByPositionId(position.getId());
            permissionList = MenuUtil.extractIncludeRemove(permissionIncludeIdList, permissionList);
            for (Permission permissionInner : permissionList) {
                positionAuthorityMapper.removeByPositionIdAndAuthorityId(position.getId(), permissionInner.getId());
                Permission tempPermission = new Permission();
                tempPermission.setId(permissionInner.getId());
                tempPermission.setPositionCount(permissionInner.getPositionCount() - 1);
                permissionMapper.update(tempPermission);
            }
            // 查找所有职位人员，清楚redis强制重新登录
            List<PositionOrgUser> removeRedisData = positionOrgUserMapper.findByPositionId(positionAuthorityRemoveVO.getPositionId());
            for (PositionOrgUser positionOrgUser : removeRedisData) {
                RedisUtil.deleteFold("caiden_micheal:user:" + positionOrgUser.getUserId() + ":*");
            }
            return AjxResult.success("移除成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult positionAddPermission(AddPositionPermissionVO addPositionPermissionVO) {
        if (addPositionPermissionVO == null || addPositionPermissionVO.getAuthorityIds() == null || addPositionPermissionVO.getPositionId() == null) {
            return AjxResult.paramError("参数传入错误");
        }
        Position position = positionMapper.findById(addPositionPermissionVO.getPositionId());
        if (position == null) {
            return AjxResult.paramError("职位不存在");
        }
        List<Permission> permissionList = permissionMapper.findBatchByIds(addPositionPermissionVO.getAuthorityIds());
        if (permissionList == null) {
            return AjxResult.paramError("权限均不存在");
        }
        try {
            MenuUtil.permissionListMerging(permissionList, menuService);
            List<Long> existsPermissionIdList = positionAuthorityMapper.findAuthorityIdsByPositionId(position.getId());
            permissionList = MenuUtil.excludeExistPermission(existsPermissionIdList, permissionList);
            positionAuthorityMapper.batchAddByAuthorityListAndPosition(permissionList, position);
            List<Long> permissionIdList = new ArrayList<>();
            for (Permission permission : permissionList) {
                permissionIdList.add(permission.getId());
            }
            permissionMapper.updatePositionCountByIds(permissionIdList, true);
            return AjxResult.success("添加成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Override
    public AjxResult findPosiitonTreeByOrg(Long orgId) {
        if (orgId == null) {
            logger.warn("Parameter transmission error! orgId:" + orgId);
            return AjxResult.paramError("参数传递有误");
        }
        List<PositionOrgUser> positionOrgUserList = positionOrgUserMapper.findByOrgId(orgId);
        if (positionOrgUserList == null || positionOrgUserList.size() == 0) {
            return AjxResult.paramError("该部门尚无人员任职");
        }
        List<Long> userIdList = new ArrayList<>();
        List<Long> positionIdList = new ArrayList<>();
        Map<Long, Long> positionUserMap = new HashMap<>();
        for (PositionOrgUser positionOrgUser : positionOrgUserList) {
            userIdList.add(positionOrgUser.getUserId());
            positionIdList.add(positionOrgUser.getPositionId());
            positionUserMap.put(positionOrgUser.getPositionId(), positionOrgUser.getUserId());
        }
        List<Position> positionList = positionMapper.findByIds(positionIdList);
        List<User> userList = userMapper.findUserListByIds(userIdList);
        Position position = recursiveQueryPosition(0, positionUserMap, positionList, userList);
        ArrayList<Position> resultData = new ArrayList<>();
        if (position != null) {
            resultData.add(position);
        }
        return AjxResult.success(resultData);
    }

    private Position recursiveQueryPosition(Integer index, Map<Long, Long> positionUserMap, List<Position> positionList, List<User> userList) {
        if (index >= positionList.size()) {
            return null;
        }
        Position position = positionList.get(index);
        for (User user : userList) {
            if (Objects.equals(positionUserMap.get(position.getId()), user.getId())) {
                position.setUser(user.getName());
            }
        }
        Position childPosition = recursiveQueryPosition(++index, positionUserMap, positionList, userList);
        ArrayList<Position> resultData = new ArrayList<>();
        if (childPosition != null) {
            resultData.add(childPosition);
        }
        position.setChild(resultData);
        return position;
    }

    @Transactional
    @Override
    public AjxResult addPosition(AddPositionVO addPositionVO) {
        if (addPositionVO == null || addPositionVO.getPositionName() == null || addPositionVO.getRank() == null || addPositionVO.getCreationDate() == null) {
            logger.warn(LoggerHead.warnHead() + "addPositionVO has error! addPositionVO: " + addPositionVO);
            return AjxResult.paramError("参数传入有误");
        }
        try {
            Position tempPosition = positionMapper.findByName(addPositionVO.getPositionName());
            if (tempPosition != null) {
                return AjxResult.paramError("职位名称已存在，请更换后重试");
            }
            tempPosition = positionMapper.findByRank(addPositionVO.getRank());
            if (tempPosition != null) {
                return AjxResult.paramError("职位级别已存在，请更换后重试");
            }
            Position position = new Position();
            BeanUtils.copyProperties(addPositionVO, position);
            positionMapper.addPosition(position);
            return AjxResult.success("添加成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult removePositionUser(RemovePositionUserVO removePositionUserVO) {
        if (removePositionUserVO == null || removePositionUserVO.getPositionId() == null || removePositionUserVO.getUserId() == null) {
            return AjxResult.paramError("参数传入错误");
        }
        Position tempPosition = positionMapper.findById(removePositionUserVO.getPositionId());
        if (tempPosition == null) {
            return AjxResult.paramError("职位不存在");
        }
        try {
            positionOrgUserMapper.removeByUserIdAndPositionIdAndOrgId(removePositionUserVO.getUserId(), removePositionUserVO.getPositionId(), removePositionUserVO.getOrgId());
            Position position = new Position();
            position.setId(removePositionUserVO.getPositionId());
            position.setUserCount(tempPosition.getUserCount() - 1);
            positionMapper.updatePosition(position);
            // 强制用户重新登录
            RedisUtil.deleteFold("caiden_micheal:user:" + removePositionUserVO.getUserId() + ":*");
            return AjxResult.success("移除成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult editPosition(EditPositionVO editPositionVO) {
        if (editPositionVO == null || editPositionVO.getId() == null || editPositionVO.getPositionName() == null || editPositionVO.getRank() == null || editPositionVO.getCreationDate() == null) {
            return AjxResult.paramError("参数传入有误");
        }
        try {
            Position tempPosition = positionMapper.findById(editPositionVO.getId());
            if (tempPosition == null) {
                return AjxResult.passwordError("职位不存在");
            }
            Position resPosition = new Position();
            resPosition.setId(tempPosition.getId());

            if (!Objects.equals(editPositionVO.getPositionName(), tempPosition.getPositionName())) {
                Position position = positionMapper.findByName(editPositionVO.getPositionName());
                if (position != null) {
                    return AjxResult.paramError("职位名称已存在，请更换后重试");
                } else {
                    resPosition.setPositionName(editPositionVO.getPositionName());
                }
            }
            if (!Objects.equals(editPositionVO.getRank(), tempPosition.getRank())) {
                Position position = positionMapper.findByRank(editPositionVO.getRank());
                if (position != null) {
                    return AjxResult.paramError("职位级别已存在，请更换后重试");
                } else {
                    resPosition.setRank(editPositionVO.getRank());
                }
            }
            if (!editPositionVO.getCreationDate().equals(tempPosition.getCreationDate())) {
                resPosition.setCreationDate(editPositionVO.getCreationDate());
            }
            if (resPosition.getPositionName() != null || resPosition.getCreationDate() != null || resPosition.getRank() != null) {
                positionMapper.updatePosition(resPosition);
            }
            if (resPosition.getPositionName() != null) {
                positionAuthorityMapper.updatePositionName(resPosition);
            }
            return AjxResult.success("修改成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult addAllocationPosition(PositionOrgUser positionOrgUser) {
        if (positionOrgUser == null || positionOrgUser.getPositionId() == null || positionOrgUser.getUserId() == null || positionOrgUser.getOrgId() == null) {
            return AjxResult.paramError("传入参数有误");
        }
        Org org = orgMapper.findById(positionOrgUser.getOrgId());
        if (org == null) {
            return AjxResult.paramError("未找到入参的机构");
        }
        try {
            PositionOrgUser tempPositionOrgUser = new PositionOrgUser();
            tempPositionOrgUser.setPositionId(positionOrgUser.getPositionId());
            tempPositionOrgUser.setOrgId(positionOrgUser.getOrgId());
            tempPositionOrgUser.setOrgName(org.getOrgName());
            tempPositionOrgUser.setUserId(positionOrgUser.getUserId());
            positionOrgUserMapper.save(tempPositionOrgUser);
            Position position = positionMapper.findById(positionOrgUser.getPositionId());
            Position tempPosition = new Position();
            tempPosition.setId(positionOrgUser.getPositionId());
            tempPosition.setUserCount(position.getUserCount() + 1);
            positionMapper.updatePosition(tempPosition);
            return AjxResult.success("新增成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult removePosition(PositionRemoveVO positionRemoveVO) {
        Position position = positionMapper.findById(positionRemoveVO.getPositionId());
        if (position == null) {
            return AjxResult.passwordError("职位信息不存在");
        }
        try {
            positionMapper.remove(position);
            List<Long> authorityIds = positionAuthorityMapper.findAuthorityIdsByPositionId(positionRemoveVO.getPositionId());
            permissionMapper.updatePositionCountByIds(authorityIds, false);
            positionAuthorityMapper.removeByPositionId(positionRemoveVO.getPositionId());
            positionOrgUserMapper.removeByPositionId(positionRemoveVO.getPositionId());
            return AjxResult.success("删除成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    @Transactional
    @Override
    public AjxResult addPermission(PositionPermissionQueryVO positionPermissionQueryVO) {
        if (positionPermissionQueryVO == null || positionPermissionQueryVO.getPositionIds() == null || positionPermissionQueryVO.getAuthorityId() == null) {
            return AjxResult.paramError("参数传递有误");
        }
        Permission permission = permissionMapper.findById(positionPermissionQueryVO.getAuthorityId());
        if (permission == null) {
            return AjxResult.paramError("权限不存在");
        }
        List<Position> positionList = positionMapper.findByIds(positionPermissionQueryVO.getPositionIds());
        if (positionList.size() == 0) {
            return AjxResult.paramError("职位不存在");
        }
        try {
            ArrayList<Permission> permissionList = new ArrayList<>();
            permissionList.add(permission);
            MenuUtil.permissionListMerging(permissionList, menuService);
            for (Permission permissionInner : permissionList) {
                positionList = excludeExistPosition(positionList, permissionInner);
                if (positionList.size() == 0) {
                    break;
                }
                positionAuthorityMapper.batchAdd(positionList, permissionInner);
                Permission tempPermission = new Permission();
                tempPermission.setId(permissionInner.getId());
                tempPermission.setPositionCount(permissionInner.getPositionCount() + positionList.size());
                permissionMapper.update(tempPermission);
            }
            return AjxResult.success("添加成功");
        } catch (Exception e) {
            logger.error(e.toString());
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return AjxResult.unknownError("数据库操作异常");
        }
    }

    private List<Position> excludeExistPosition(List<Position> positionList, Permission permissionInner) {
        List<Long> existIdList = positionAuthorityMapper.findPositionIdsByAuthorityId(permissionInner.getId());
        ArrayList<Position> tempPositionList = new ArrayList<>();
        for (Position position : positionList) {
            if (!existIdList.contains(position.getId())) {
                tempPositionList.add(position);
            }
        }
        return tempPositionList;
    }
}